#include "fs.h"

int dev, root_dir, number_of_inode_blocks;
void *sb;
int mounted;

// --------------------------------------------------------------
int sd_close(int fd)
{
	return -1;
} // sd_close

// --------------------------------------------------------------
sd_info_t* sd_info(const char* filename)
{
	return NULL;
} // sd_info

// --------------------------------------------------------------
int sd_mkdir(const char* dirname)
{
	return -1;
} // sd_mkdir

// --------------------------------------------------------------
int sd_mount(const char* device, const char* mount_point)
{
	int i, j;
	void *tmp_node, *block;
	s5_inode_t tmp;
	
	// Already mounted?
	if (mounted != 0)
	{
		printf("A disk is already mounted! Unmount before mounting another one!\n");
		return -1;
	}

	// Init device
	printf("Mounting disk %s...", device);
	if ((dev = init_device(device)) != 0)
	{
		printf("%s is not a simdisk\n", device);
		return -1;
	}
	printf(" Done!\n");

	// Read superblock
	printf("Reading superblock...");
	if (!(sb = read_block(dev, ((s5_super_t *)sb))))
	{
		printf("Could not read superblock\n");
		return -1;
	}
	printf(" Done!\n");
	
	// Print superblock
	printf("s5s_magic: %#x\t%d\n", ((s5_super_t *)sb)->s5s_magic, ((s5_super_t *)sb)->s5s_magic);
	printf("s5s_free_inode: %#x\t%d\n", ((s5_super_t *)sb)->s5s_free_inode, ((s5_super_t *)sb)->s5s_free_inode);
	printf("s5s_free_block: %#x\t%d\n", ((s5_super_t *)sb)->s5s_free_block, ((s5_super_t *)sb)->s5s_free_block);
	printf("s5s_root_inode: %#x\t%d\n", ((s5_super_t *)sb)->s5s_root_inode, ((s5_super_t *)sb)->s5s_root_inode);
	printf("s5s_num_inodes: %#x\t%d\n", ((s5_super_t *)sb)->s5s_num_inodes, ((s5_super_t *)sb)->s5s_num_inodes);
	printf("s5s_num_dblocks: %#x\t%d\n", ((s5_super_t *)sb)->s5s_num_dblocks, ((s5_super_t *)sb)->s5s_num_dblocks);
	printf("s5s_version: %#x\t%d\n", ((s5_super_t *)sb)->s5s_version, ((s5_super_t *)sb)->s5s_version);
	
	// Save root dir
	root_dir = ((s5_super_t *)sb)->s5s_root_inode;
		
	// Read number of inode blocks
	number_of_inode_blocks = ((s5_super_t *)sb)->s5s_num_inodes / S5_INODES_PER_BLOCK;
	printf("Number of inode blocks: %d\n", number_of_inode_blocks);
	
	// Set mounted flag
	mounted = 1;
	printf("Disk mounted!\n");
	
	// Test injection of data (works!)
	//((s5_super_t *)sb)->s5s_magic = 0xDA2012;
	//write_block(dev, sb, S5_SUPER_BLOCK);
	

	// // DEBUG WRITING

	// printf("s5s_magic: %#x\t%d\n", ((s5_super_t *)sb)->s5s_magic, ((s5_super_t *)sb)->s5s_magic);
	// printf("s5s_free_inode: %#x\t%d\n", ((s5_super_t *)sb)->s5s_free_inode, ((s5_super_t *)sb)->s5s_free_inode);
	// printf("s5s_free_block: %#x\t%d\n", ((s5_super_t *)sb)->s5s_free_block, ((s5_super_t *)sb)->s5s_free_block);
	// printf("s5s_root_inode: %#x\t%d\n", ((s5_super_t *)sb)->s5s_root_inode, ((s5_super_t *)sb)->s5s_root_inode);
	// printf("s5s_num_inodes: %#x\t%d\n", ((s5_super_t *)sb)->s5s_num_inodes, ((s5_super_t *)sb)->s5s_num_inodes);
	// printf("s5s_num_dblocks: %#x\t%d\n", ((s5_super_t *)sb)->s5s_num_dblocks, ((s5_super_t *)sb)->s5s_num_dblocks);
	// printf("s5s_version: %#x\t%d\n", ((s5_super_t *)sb)->s5s_version, ((s5_super_t *)sb)->s5s_version);
	// printf("\nTotal number of blocks: %d\n", ((s5_super_t *)sb)->s5s_num_dblocks + ((s5_super_t *)sb)->s5s_num_inodes / S5_INODES_PER_BLOCK);	
	// printf("\nNumber of INODE blocks: %d\n\n", number_of_inode_blocks);

	// tmp_node = read_block(dev, 1); // READ BLOCK 1
	// memcpy(&tmp, &((s5_inode_t *)tmp_node)[0], sizeof(s5_inode_t));
	// printf("free_or_size: %d\n", tmp.s5_free_or_size);
	// printf("number_of_inode_blocks: %d\n", number_of_inode_blocks);
	// printf("s5_direct_blocks: %d\n", tmp.s5_direct_blocks);
	// for (i = 0; i < tmp.s5_free_or_size && i <= S5_DIRECT_BLOCKS * S5_BLOCK_SIZE; i += S5_BLOCK_SIZE)
	// {
		// printf("i / S5_BLOCK_SIZE: %d\n", i / S5_BLOCK_SIZE);
		// printf("number_of_inode_blocks + tmp.s5_direct_blocks[i / S5_BLOCK_SIZE]: %d\n", 
			// number_of_inode_blocks + tmp.s5_direct_blocks[i / S5_BLOCK_SIZE]);
		// if(!(block = read_block(dev, number_of_inode_blocks + tmp.s5_direct_blocks[i / S5_BLOCK_SIZE])))
		// {
			// printf("Could not read block\n");
			// return -1;
		// }
		// for (j = 0; j < (tmp.s5_free_or_size - i) / sizeof(s5_dirent_t); ++j)
			// printf("%s\t%#x\n", ((s5_dirent_t *)block)[j].s5d_name, ((s5_dirent_t *)block)[j].s5d_inode);
	// }
	

	//tmp_node = read_block(dev, ((s5_super_t *)((s5_super_t *)sb))->s5s_root_inode);
	//printf("s5_free_or_size: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_free_or_size, ((s5_inode_t *)tmp_node)->s5_free_or_size);
	//printf("s5_number: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_number, ((s5_inode_t *)tmp_node)->s5_number);
	//printf("s5_type: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_type, ((s5_inode_t *)tmp_node)->s5_type);
	//printf("s5_numrefs: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_numrefs, ((s5_inode_t *)tmp_node)->s5_numrefs);
	//printf("s5_direct_blocks: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_direct_blocks, ((s5_inode_t *)tmp_node)->s5_direct_blocks);
	//printf("s5_indirect_block: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_indirect_block, ((s5_inode_t *)tmp_node)->s5_indirect_block);
	//
	//tmp_node = read_block(dev, ((s5_super_t *)((s5_super_t *)sb))->s5s_free_inode);
	//printf("s5_free_or_size: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_free_or_size, ((s5_inode_t *)tmp_node)->s5_free_or_size);
	//printf("s5_number: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_number, ((s5_inode_t *)tmp_node)->s5_number);
	//printf("s5_type: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_type, ((s5_inode_t *)tmp_node)->s5_type);
	//printf("s5_numrefs: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_numrefs, ((s5_inode_t *)tmp_node)->s5_numrefs);
	//printf("s5_direct_blocks: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_direct_blocks, ((s5_inode_t *)tmp_node)->s5_direct_blocks);
	//printf("s5_indirect_block: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_indirect_block, ((s5_inode_t *)tmp_node)->s5_indirect_block);
	//
	//tmp_node = read_block(dev, ((s5_super_t *)((s5_super_t *)sb))->s5s_free_block);
	//printf("s5_free_or_size: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_free_or_size, ((s5_inode_t *)tmp_node)->s5_free_or_size);
	//printf("s5_number: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_number, ((s5_inode_t *)tmp_node)->s5_number);
	//printf("s5_type: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_type, ((s5_inode_t *)tmp_node)->s5_type);
	//printf("s5_numrefs: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_numrefs, ((s5_inode_t *)tmp_node)->s5_numrefs);
	//printf("s5_direct_blocks: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_direct_blocks, ((s5_inode_t *)tmp_node)->s5_direct_blocks);
	//printf("s5_indirect_block: %#x\t%d\n", ((s5_inode_t *)tmp_node)->s5_indirect_block, ((s5_inode_t *)tmp_node)->s5_indirect_block);

	

	// DEBUG WRITING

	//((s5_super_t *)((s5_super_t *)sb))->s5s_magic = 0xDA2012;
	//if (write_block(dev, ((s5_super_t *)sb), S5_((s5_super_t *)sb)) != 0)
	//	goto error;

	// Close device
	close_device(dev);
	return 0;
} // sd_mount

// --------------------------------------------------------------
int sd_open(const char* filename, int create)
{
	return -1;
} // sd_open

// --------------------------------------------------------------
int sd_read(int fd, void* buf, int nbyte)
{
	return -1;
} // sd_read

// --------------------------------------------------------------
char** sd_readdir(const char* dirname)
{
	return NULL;
} // sd_readdir

// --------------------------------------------------------------
int sd_rename(const char* oldname, const char* newname)
{
	return -1;
} // sd_rename

// --------------------------------------------------------------
int sd_rmdir(const char* dirname)
{
	return -1;
} // sd_rmdir

// --------------------------------------------------------------
int sd_rmfile(const char* filename)
{
	return -1;
} // sd_rmfile

// --------------------------------------------------------------
int sd_umount(const char* mount_point)
{
	if (mounted != 0)
	{
		printf("Unmounting disk...");
		dev = mounted = number_of_inode_blocks = root_dir = 0;
		sb = NULL;
		printf(" Done!\n");
	}
	else
	{
		printf("No disk mounted\n");
	}
	
	return mounted;
} // sd_unmount

// --------------------------------------------------------------
int sd_write(int fd, const void* buf, int nbyte)
{
	return -1;
} // sd_write
